// 
// SoapTrace.Net - A soap message monitoring utility. 
// 
// Copyright (C) 2004-2009 Matthew Ward
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// 
// Matthew Ward (mrward@users.sourceforge.net)
// 

using NUnit.Framework;
using System;
using WinPcap.Tests.Configuration;
using WinPcap.Tests.Utils;

namespace WinPcap.Tests
{
	/// <summary>
	/// Tests for the NetworkInterface class.
	/// </summary>
	[ TestFixture ]
	public class NetworkInterfaceTestFixture
	{
		/// <summary>
		/// A network interface object that will be used to test the
		/// Equals comparison.
		/// </summary>
		private NetworkInterface m_NetworkInterface = null;

		/// <summary>
		/// A network interface object that is logically the same as the
		/// m_NetworkInterface object 
		/// </summary>
		private NetworkInterface m_MatchingNetworkInterface;

		/// <summary>
		/// A network interface object that is logically the same as the
		/// m_NetworkInterface object 
		/// </summary>
		private NetworkInterface m_NonMatchingNetworkInterface;

		/// <summary>
		/// Initialises each test.
		/// </summary>
		[ SetUp ]
		public void Init( )
		{
			m_NetworkInterface = new NetworkInterface( );
			m_NetworkInterface.Description = "Description";
			m_NetworkInterface.IsLoopback = true;
			m_NetworkInterface.Name = "Name";
			m_NetworkInterface.DataLinkLayerType = DataLinkLayerType.Ethernet;

			m_MatchingNetworkInterface = new NetworkInterface( );
			m_MatchingNetworkInterface.Description = "Description";
			m_MatchingNetworkInterface.IsLoopback = true;
			m_MatchingNetworkInterface.Name = "Name";
			m_MatchingNetworkInterface.DataLinkLayerType = DataLinkLayerType.Ethernet;

			// Set the non-matching object to match initially.  Each
			// test will change one property and check that the match
			// fails.
			m_NonMatchingNetworkInterface = new NetworkInterface( );
			m_NonMatchingNetworkInterface.Description = "Description";
			m_NonMatchingNetworkInterface.IsLoopback = true;
			m_NonMatchingNetworkInterface.Name = "Name";
			m_NonMatchingNetworkInterface.DataLinkLayerType = DataLinkLayerType.Ethernet;
		}

		/// <summary>
		/// Tests that the Equals method works.
		/// </summary>
		[ Test ]
		public void Match( )
		{
			Assert.AreEqual( m_NetworkInterface,
				m_MatchingNetworkInterface,
				"Network interfaces do not match." );
		}

		/// <summary>
		/// Tests that a difference in the description causes Equals to fail.
		/// </summary>
		[ Test ]
		public void DescriptionMismatchOnly( )
		{
			m_NonMatchingNetworkInterface.Description = "Blah";

			Assert.IsFalse(
				m_NetworkInterface.Equals( m_NonMatchingNetworkInterface ),
				"Description is different so Equals should fail." );
		}

		/// <summary>
		/// Tests that a difference in the name causes Equals to fails
		/// </summary>
		[ Test ]
		public void NameMismatchOnly( )
		{
			m_NonMatchingNetworkInterface.Name = "Blah";

			Assert.IsFalse( 
				m_NetworkInterface.Equals( m_NonMatchingNetworkInterface ),
				"Name is different so Equals should fail." );
		}

		/// <summary>
		/// Tests that a difference in the IsLoopback  causes Equals to fail.
		/// </summary>
		[ Test ]
		public void IsLoopbackMismatchOnly( )
		{
			m_NonMatchingNetworkInterface.IsLoopback = ! m_NetworkInterface.IsLoopback;

			Assert.IsFalse( m_NetworkInterface.Equals( 
				m_NonMatchingNetworkInterface ),
				"Name is different so Equals should fail." );
		}

		/// <summary>
		/// Tests that a difference in the data link layer causes Equals to
		/// fail.
		/// </summary>
		[ Test ]
		public void DataLinkLayerTypeMismatchOnly( )
		{
			m_NonMatchingNetworkInterface.DataLinkLayerType = DataLinkLayerType.Raw;

			Assert.IsFalse( m_NetworkInterface.Equals( 
				m_NonMatchingNetworkInterface ),
				"Data linke layer is different so Equals should fail." );
		}
		
		/// <summary>
		/// Tests that opening a network interface with an invalid
		/// device name throws an exception.
		/// </summary>
		[ Test ]
		[ ExpectedException( typeof( WinPcapException ), 
			ExpectedMessage = "No network interface found with name INVALID_NETWORK_DEVICE_NAME." ) ]
		public void OpenUnknownNetworkInterface( )
		{
			NetworkInterface NetworkInterface = new NetworkInterface( );
			NetworkInterface.Open( "INVALID_NETWORK_DEVICE_NAME" );
		}
		
		/// <summary>
		/// Tests that opening a network interface with a correct
		/// name succeeds.
		/// </summary>
		[ Test ]
		public void OpenKnownNetworkInterface( )
		{
			NetworkInterface NetworkInterface = new NetworkInterface( );
			NetworkInterface.Open( TestConfig.NetworkInterfaces[ 0 ].Name );
			NetworkInterface.Close( );
		}
		
		/// <summary>
		/// Makes so that a network interface with no netmask is handled.
		/// The <see cref="NetworkInterface.Open"/> method was assuming
		/// that we always had at least one netmask.
		/// </summary>
		[ Test ]
		public void OpenNetworkInterfaceWithNoNetmask( )
		{
			NetworkInterface NetworkInterface = new NetworkInterface( );
			NetworkInterface.Name = TestConfig.NetworkInterfaces[ 0 ].Name;
			NetworkInterface.Open( );
			NetworkInterface.Close( );
		}
		
		/// <summary>
		/// Makes sure the NetworkInterface class does not throw
		/// an exception trying to close a network interface which
		/// is not open.
		/// </summary>
		[ Test ]
		public void CloseNetworkInterfaceWithoutOpening( )
		{
			NetworkInterface NetworkInterface = new NetworkInterface( );
			NetworkInterface.Name = TestConfig.NetworkInterfaces[ 0 ].Name;
			NetworkInterface.Close( );
		}
		
		/// <summary>
		/// Tests that we receive an ObjectDisposedException if we 
		/// try to Open a NetworkInterface class after we have closed it.
		/// </summary>
		[ Test ]
		[ ExpectedException( typeof( ObjectDisposedException ) ) ]
		public void CloseThenOpenKnownNetworkInterface( )
		{
			NetworkInterface NetworkInterface = new NetworkInterface( );
			NetworkInterface.Open( TestConfig.NetworkInterfaces[ 0 ].Name );
			NetworkInterface.Close( );
			NetworkInterface.Open( TestConfig.NetworkInterfaces[ 0 ].Name );
		}
	}
}
